Electronic systems are used in a variety of products, from automobiles to microwaves to personal computers. Designing and fabricating these electronic system typically involves many steps, known as a “design flow.” The particular steps of a design flow often are dependent upon the type of electronic system, its complexity, the design team, and the electronic system fabricator or foundry that will manufacture the electronic system. Typically, software and hardware “tools” verify the design at various stages of the design flow by running software simulators and/or hardware emulators, and errors in the design are corrected or the design is otherwise improved.
Several steps are common to most design flows for electronic system. Initially, the specification for a new circuit is transformed into a logical design, sometimes referred to as a register transfer level (RTL) description of the circuit. With this logical design, the circuit can be described in terms of both the exchange of signals between hardware registers and the logical operations that can be performed on those signals. The logical design typically employs a Hardware Design Language (HDL), such as the Very high speed integrated circuit Hardware Design Language (VHDL). The logic of the circuit is then analyzed, to confirm that it will accurately perform the functions desired for the circuit. This analysis is sometimes referred to as “functional verification.”
Functional verification typically begins with a circuit design coded at the register transfer level, which can be simulated by a design verification tool. A designer can generate a test bench that, when simulated with the circuit design, can allow the design verification tool to analyze the functionality of the simulated circuit design. When the simulated circuit design operates differently than expected in response to stimulus from the test bench, the designer can attempt to debug the circuit design, for example, to determine which of the gates in the circuit design is incorrectly configured, resulting in the generation of illegal states or transitions.
The design verification tool can record signal states and transitions of the circuit design, often called waveform data, which the designer can review in an attempt to identify a “bug” in the circuit design. The designer typically can utilize a debug tool to review the recorded waveforms, often alongside a source code of the circuit design, in an attempt to locate and address the circuit design failure.
The presence of “bugs” in RTL code, however, is not limited to the circuit design, as test benches also can include defects. These test bench defects may be confined to providing incorrect stimulus to the simulated circuit design or improper response checking, but, in some cases, the test bench “bug” can improperly manage data and inadvertently overconsume physical memory, rendering simulation—at best—resource intensive, or—at worst—incapable of being performed.
Test benches have evolved from static configuration coded in the register-transfer level into programs that dynamically generate the test bench configuration. Many of these test benches are generated with object-oriented programming languages that are transient in nature, for example, with object components, such as classes, being created and destroyed during execution. The test benches, during simulation, can generate handles or memory pointers for these dynamically created class objects, which can be passed around for use during simulation.
One way to destroy class objects is to remove references to the class object, for example, deleting the handles or memory pointers to the class object in memory. The computing system implementing the simulation of the circuit design and test bench typically includes garbage collection functionality, which can identify portions of memory having no references and de-allocating those portions of memory, freeing them up for re-use. When a test bench includes a “bug” that inadvertently retains a handle or memory pointer to a class object, the computing system's garbage collection functionality does not destroy the class object or free up its consumed memory. Current solutions for this problem entail single stepping through the test bench during live simulation and manually reviewing the results, which can be impractical when a data space associated with the simulation gets larger.